home *** CD-ROM | disk | FTP | other *** search
/ Apple WWDC 1996 / WWDC96_1996 (CD).toast / Technology Materials / MacApp Release 10 / MacApp Release 10 - HD Ready / Libraries / Core / Sources / UClassDesc.cp < prev    next >
Encoding:
Text File  |  1996-04-03  |  15.1 KB  |  581 lines  |  [TEXT/MPS ]

  1. //----------------------------------------------------------------------------------------
  2. // UClassDesc.cp
  3. // Copyright © 1984-96 by Apple Computer, Inc. All rights reserved.
  4. //----------------------------------------------------------------------------------------
  5.  
  6. #ifndef __UCLASSDESC__
  7. #include "UClassDesc.h"
  8. #endif
  9.  
  10. // MacApp
  11.  
  12. #ifndef __UCLASSDESCITERATOR__
  13. #include "UClassDescIterator.h"
  14. #endif
  15.  
  16. #ifndef __UDEBUG__
  17. #include "UDebug.h"
  18. #endif
  19.  
  20. #ifndef __UCOREERRORMGR__
  21. #include "UCoreErrorMgr.h"
  22. #endif
  23.  
  24. #ifndef __UFAILURE__
  25. #include "UFailure.h"
  26. #endif
  27.  
  28. #ifndef __ULIST__
  29. #include "UList.h"
  30. #endif
  31.  
  32. #ifndef __UTHEDEBUGGER__
  33. #include "UTheDebugger.h"
  34. #endif
  35.  
  36. // Toolbox
  37.  
  38. #ifndef __TYPES__
  39. #include <Types.h>
  40. #endif
  41.  
  42. // ANSI
  43.  
  44. #ifndef __STRING__
  45. #include <string.h>
  46. #endif
  47.  
  48. #if qDebugMsg
  49. #ifndef __STDIO__
  50. #include <stdio.h>
  51. #endif
  52. #endif
  53.  
  54.  
  55. //========================================================================================
  56. // GLOBALS
  57. //========================================================================================
  58.  
  59. #if qDebug
  60. static void ClassDescInheritanceCheck();
  61. #endif
  62.  
  63. //========================================================================================
  64. // CLASS ClassDesc
  65. //========================================================================================
  66. #pragma segment ClassDescRes
  67.  
  68. //----------------------------------------------------------------------------------------
  69. // Static Data Members:
  70. //----------------------------------------------------------------------------------------
  71.  
  72. // "Variables with storage class static that are not initialized are guaranteed to start
  73. // off as 0 converted to the appropriated type." ARM §8.4.
  74. //
  75. // Don't initialize the following static variable. It will be NULL at startup as described
  76. // above. When a global ClassDesc object is constructed it is added to this linked list.
  77. // C++ doesn't guarentee initialization order so if we initialize this to NULL and one
  78. // of the global ClassDesc objects has already been constructed and added itself to this
  79. // list, we will clobber the list if we initialize fgClassDescList to NULL.
  80.  
  81. TClassDescListByName* ClassDesc::fgClassDescListByName;
  82. TClassDescListByID* ClassDesc::fgClassDescListByID;
  83. ClassDesc* ClassDesc::fgClassDescList;
  84. TClassDescSignatureList* ClassDesc::fgSignatures;
  85. ClassID ClassDesc::fgNextClassID;
  86.  
  87. //----------------------------------------------------------------------------------------
  88. // Static Member Functions:
  89. //----------------------------------------------------------------------------------------
  90.  
  91. //----------------------------------------------------------------------------------------
  92. // ClassDesc::GetClassDescFromClassID:
  93. //----------------------------------------------------------------------------------------
  94. #pragma segment ClassDescRes
  95. MA_ClassReference ClassDesc::GetClassDescFromClassID(ClassID classID)
  96. {
  97.     return fgClassDescListByID->FindByID(classID);
  98. }
  99.  
  100. //----------------------------------------------------------------------------------------
  101. // ClassDesc::GetClassDescFromClassName:
  102. //----------------------------------------------------------------------------------------
  103. #pragma segment ClassDescRes
  104. MA_ClassReference ClassDesc::GetClassDescFromClassName(const ClassName& className)
  105. {
  106.     return fgClassDescListByName->FindByName(className);
  107. }
  108.  
  109. //----------------------------------------------------------------------------------------
  110. // ClassDesc::GetClassDescFromSignature:
  111. //----------------------------------------------------------------------------------------
  112. #pragma segment ClassDescRes
  113. MA_ClassReference ClassDesc::GetClassDescFromSignature(IDType signature)
  114. {
  115.     return fgSignatures->FindBySignature(signature);
  116. }
  117.  
  118. //----------------------------------------------------------------------------------------
  119. // ClassDesc::IsValidClassID:
  120. //----------------------------------------------------------------------------------------
  121. #pragma segment ClassDescRes
  122.  
  123. Boolean ClassDesc::IsValidClassID(ClassID classID)
  124. {
  125.     // between 1 and number of classes
  126.     return 1 <= classID && classID <= fgNextClassID;
  127. }
  128.  
  129. //----------------------------------------------------------------------------------------
  130. // ClassDesc::NewByClassID:
  131. //----------------------------------------------------------------------------------------
  132. #pragma segment ClassDescRes
  133.  
  134. void* ClassDesc::NewByClassID(ClassID classID)
  135. {
  136.     void* returnVal = NULL;
  137.  
  138.     MA_ClassReference classDesc = ClassDesc::GetClassDescFromClassID(classID);
  139.  
  140.     if (classDesc)
  141.         returnVal = classDesc->Call_DefaultConstructor();
  142.     else
  143.     {
  144. #if qDebug
  145.         ProgramBreak("The application doesn't contain the class with class ID " + CStr255(classID) + ".");
  146. #endif
  147.  
  148.         gErrorParm3 = CStr255(classID);            // show ID of the class 
  149.         Failure(errMissingClass, 0);
  150.     }
  151.  
  152.     return returnVal;
  153. }
  154.  
  155. //----------------------------------------------------------------------------------------
  156. // ClassDesc::NewByClassName:
  157. //----------------------------------------------------------------------------------------
  158. #pragma segment ClassDescRes
  159.  
  160. void* ClassDesc::NewByClassName(const ClassName& className)
  161. {
  162.     void* returnVal = NULL;
  163.  
  164.     MA_ClassReference classDesc = ClassDesc::GetClassDescFromClassName(className);
  165.  
  166.     if (classDesc)
  167.         returnVal = classDesc->Call_DefaultConstructor();
  168.     else
  169.     {
  170. #if qDebug
  171.         ProgramBreak("The application doesn't contain the class " + className + ".");
  172. #endif
  173.  
  174.         gErrorParm3 = className;                // show name of the class 
  175.         Failure(errMissingClass, 0);
  176.     }
  177.  
  178.     return returnVal;
  179. }
  180.  
  181. //----------------------------------------------------------------------------------------
  182. // ClassDesc::NewBySignature:
  183. //----------------------------------------------------------------------------------------
  184. #pragma segment ClassDescRes
  185.  
  186. void* ClassDesc::NewBySignature(IDType signature)
  187. {
  188.     void* returnVal = NULL;
  189.  
  190.     MA_ClassReference classDesc = ClassDesc::GetClassDescFromSignature(signature);
  191.  
  192.     if (classDesc)
  193.         returnVal = classDesc->Call_DefaultConstructor();
  194.     else
  195.     {
  196. #if qDebugMsg
  197.         fprintf(stderr, "signature='%4s'\n", (char*) & signature);
  198.         ProgramBreak("Unable to find class for the given signature");
  199. #endif
  200.  
  201.         Failure(errMissingSignature, 0);
  202.     }
  203.  
  204.     return returnVal;
  205. }
  206.  
  207. //----------------------------------------------------------------------------------------
  208. // ClassDesc::InitUClassDesc:
  209. //----------------------------------------------------------------------------------------
  210. #pragma segment MAInit
  211.  
  212. void ClassDesc::InitUClassDesc()
  213. {
  214.     // Build the sorted class lists. These have to be built sometime after InitUMemory.
  215.     // It would be nice to be able to do this at static initialization time.
  216.  
  217.     MAVolatileInit(TClassDescListByName * , byName, NULL);
  218.     MAVolatileInit(TClassDescListByID * , byID, NULL);
  219.     MAVolatileInit(TClassDescSignatureList * , signatures, NULL);
  220.  
  221.     FailInfo fi;
  222.     Try(fi)
  223.     {
  224.         // build sorted lists of ClassDesc from linked list
  225.         ArrayIndex numberOfClasses = fgNextClassID;
  226.  
  227. #if qTheDebugger
  228.         TheDbgr_Adjust_ClassDescr_Ids(fgClassDescList, numberOfClasses);// re-order the Class ID's
  229. #endif
  230.  
  231.         byName = new TClassDescListByName;
  232.         byName->IClassDescListByName(numberOfClasses);
  233.  
  234.         byID = new TClassDescListByID;
  235.         byID->IClassDescListByID(numberOfClasses);
  236.  
  237.         CClassIterator iter;
  238.         MA_ClassReference classDesc;
  239.  
  240.         for (classDesc = iter.FirstClassDesc(); iter.More(); classDesc = iter.NextClassDesc())
  241.         {
  242.             // UNORDERED - Insert the ClassDesc into the lists by name and by ID.
  243.             byName->InsertElementsBefore(byName->GetSize() + 1, &classDesc, 1);
  244.             byID->InsertElementsBefore(byID->GetSize() + 1, &classDesc, 1);
  245.         }
  246.  
  247.         // Now ORDER the lists
  248.         byName->Sort();
  249.         byID->Sort();
  250.  
  251.         // set these now, we need them in the rest
  252.         fgClassDescListByName = byName;
  253.         fgClassDescListByID = byID;
  254.  
  255. #if qTheDebugger
  256.         gExtDbgr_Info.n_classes = byID->GetSize();
  257.  
  258.         gExtDbgr_Info.pOrderedClass = (T_ClassList * *) & byID->fArraySpace;// pointer to pointer to array of ClassDesc
  259.         gExtDbgr_Info.MA_ClassTblPtr = (T_ClassList * *) & byName->fArraySpace;// pointer to pointer to array of ClassDesc
  260. #endif
  261.  
  262. #if qDebug
  263.         ClassDescInheritanceCheck();
  264. #endif
  265.  
  266.         signatures = new TClassDescSignatureList;
  267.         signatures->IClassDescSignatureList(0);
  268.         fgSignatures = signatures;
  269.  
  270.         fi.Success();
  271.     }
  272.     else                                        // Recover
  273.         {
  274.             if (byName)
  275.             {
  276.                 byName->DeleteAll();
  277.                 byName->Free();
  278.             }
  279.  
  280.             if (byID)
  281.             {
  282.                 byID->DeleteAll();
  283.                 byID->Free();
  284.             }
  285.  
  286.             if (signatures)
  287.             {
  288.                 signatures->DeleteAll();
  289.                 signatures->Free();
  290.             }
  291.  
  292.             fi.ReSignal();
  293.         }
  294. }
  295.  
  296. //----------------------------------------------------------------------------------------
  297. // ClassDesc::ClassDesc:
  298. //----------------------------------------------------------------------------------------
  299. #pragma segment ClassDescRes
  300.  
  301. ClassDesc::ClassDesc(const char* className,
  302.                      size_t classSize,
  303.                      MA_ClassReference const* ancestors,
  304.                      const ptrdiff_t* const offsets) :
  305.     fClassName(className),
  306.     fClassSize(classSize),
  307.     fAncestors(ancestors),
  308.     fAncestorOffsets(offsets)
  309. {
  310.     //    #if qDebug
  311.     //        // Check for duplicate class descriptor
  312.     //        CClassIterator iter;
  313.     //        MA_ClassReference classDesc;
  314.     //        for (classDesc = iter.FirstClassDesc(); iter.More(); classDesc = iter.NextClassDesc())
  315.     //        {
  316.     //            if (classDesc == this)
  317.     //            {
  318.     //                ClassName name = this->GetClassName();
  319.     //                ProgramBreak("Duplicate class descriptor for " + name + "!");
  320.     //            }
  321.     //        }
  322.     //    #endif
  323.  
  324.     // link list of ClassDesc
  325.     fNextClassDesc = fgClassDescList;
  326.     fgClassDescList = this;
  327.  
  328.     // AssignNewClassID
  329.     fClassID =++fgNextClassID;
  330. }
  331.  
  332. //----------------------------------------------------------------------------------------
  333. // ClassDesc::Call_DefaultConstructor:
  334. //----------------------------------------------------------------------------------------
  335. #pragma segment ClassDescRes
  336.  
  337. void* ClassDesc::Call_DefaultConstructor() const
  338. {
  339.     void* returnVal = NULL;
  340.  
  341.     if (fDefaultConstructor)
  342.         returnVal = (*(ConstructorProcPtr)fDefaultConstructor)();
  343.     else
  344.     {
  345.         gErrorParm3 = GetClassName();            // show name of the class 
  346. #if qDebug
  347.         ProgramBreak("Class " + gErrorParm3 + " does not appear to have been registered.");
  348. #endif
  349.  
  350.         Failure(errMissingClass, 0);
  351.     }
  352.     
  353.     return returnVal;
  354. }
  355.  
  356. //----------------------------------------------------------------------------------------
  357. // ClassDesc::CountBaseClasses:
  358. //----------------------------------------------------------------------------------------
  359. #pragma segment ClassDescRes
  360.  
  361. ArrayIndex ClassDesc::CountBaseClasses() const
  362. {
  363.     ArrayIndex count = 0;
  364.     MA_ClassReference
  365.     const* ancestors = fAncestors;
  366.  
  367.     while (*ancestors != 0)
  368.     {
  369.         count++;
  370.         ancestors++;
  371.     }
  372.  
  373.     return count;
  374. }
  375.  
  376. //----------------------------------------------------------------------------------------
  377. // ClassDesc::DynamicCast:
  378. //----------------------------------------------------------------------------------------
  379.  
  380. void* ClassDesc::DynamicCast(const void* p,
  381.                              MA_ClassReference pointersClass,
  382.                              MA_ClassReference aBaseClass) const
  383. {
  384.     ptrdiff_t offset;
  385.     char* q = 0;
  386.  
  387.     if (pointersClass == aBaseClass)
  388.     {
  389.         if (this->DescendsFrom(aBaseClass))
  390.             q = (char*)p;
  391.     }
  392.     else if (this->OffsetToBase(pointersClass, offset))
  393.     {
  394.         q = ((char*)p) - offset;
  395.         if (this->OffsetToBase(aBaseClass, offset))
  396.             q += offset;
  397.         else
  398.             q = 0;
  399.     }
  400.  
  401. #if qDebugMsg
  402.     if (!q)
  403.     {
  404.         if (gIntenseDebugging)
  405.             fprintf(stderr, "Cannot dynamic cast a %s from %s to %s\n", GetClassName(), pointersClass->GetClassName(), aBaseClass->GetClassName());
  406.     }
  407. #endif // qDebugMsg
  408.  
  409.     return q;
  410. }
  411.  
  412. //----------------------------------------------------------------------------------------
  413. // ClassDesc::GetBaseClass:
  414. //----------------------------------------------------------------------------------------
  415. #pragma segment ClassDescRes
  416.  
  417. MA_ClassReference ClassDesc::GetBaseClass(ArrayIndex index) const
  418. {
  419. #if qRangeCheck
  420.     if (index > CountBaseClasses())
  421.     {
  422. #if qDebug
  423.         ProgramBreak("Base class index out of range!");
  424. #endif
  425.  
  426.         Failure(minErr, 0);
  427.     }
  428. #endif
  429.  
  430.     return fAncestors[index - 1];
  431. }
  432.  
  433. //----------------------------------------------------------------------------------------
  434. // ClassDesc::DescendsFrom:
  435. //----------------------------------------------------------------------------------------
  436. #pragma segment ClassDescRes
  437.  
  438. IDType ClassDesc::GetSignature() const
  439. {
  440.     return fgSignatures->FindByClassDesc(this);
  441. }
  442.  
  443. //----------------------------------------------------------------------------------------
  444. // ClassDesc::DescendsFrom:
  445. //----------------------------------------------------------------------------------------
  446. #pragma segment ClassDescRes
  447.  
  448. Boolean ClassDesc::DescendsFrom(MA_ClassReference classDesc,
  449.                                 Boolean directDescendant) const
  450. {
  451.     Boolean result = FALSE;
  452.  
  453.     // Is it this class?
  454.  
  455.     if (classDesc == this)
  456.         result = TRUE;
  457.     else
  458.     {
  459.         MA_ClassReference
  460.         const* ancestors = fAncestors;
  461.  
  462.         // Is it a direct ancestor?
  463.  
  464.         while (*ancestors != 0)
  465.         {
  466.             if (*ancestors == classDesc)
  467.             {
  468.                 result = TRUE;
  469.                 break;
  470.             }
  471.             ancestors++;
  472.         }
  473.  
  474.         // Recursively check our more remote ancestors. 
  475.  
  476.         if ((!result) && (!directDescendant))
  477.         {
  478.             ancestors = fAncestors;
  479.  
  480.             while (*ancestors != 0)
  481.             {
  482.                 if ((*ancestors)->DescendsFrom(classDesc))
  483.                 {
  484.                     result = TRUE;
  485.                     break;
  486.                 }
  487.                 ancestors++;
  488.             }
  489.         }
  490.     }
  491.  
  492.     return result;
  493. }
  494.  
  495. // ClassDesc::OffsetToBase:
  496. //----------------------------------------------------------------------------------------
  497. #pragma segment ClassDescRes
  498.  
  499. void ClassDesc::RegisterSignature(IDType signature)
  500. {
  501.     fgSignatures->RegisterSignature(this, signature);
  502. }
  503.  
  504. //----------------------------------------------------------------------------------------
  505. // ClassDesc::OffsetToBase:
  506. //----------------------------------------------------------------------------------------
  507. #pragma segment ClassDescRes
  508.  
  509. Boolean ClassDesc::OffsetToBase(MA_ClassReference aBaseClass,
  510.                                 ptrdiff_t& offset) const
  511. {
  512.     Boolean result = FALSE;
  513.  
  514.     if (aBaseClass == this)
  515.     {
  516.         offset = 0;
  517.         result = TRUE;
  518.     }
  519.     else
  520.     {
  521.         MA_ClassReference
  522.         const* ancestors = fAncestors;
  523.  
  524.         while (*ancestors != 0)
  525.         {
  526.             if ((*ancestors)->OffsetToBase(aBaseClass, offset))
  527.             {
  528.                 offset += fAncestorOffsets[ancestors - fAncestors];
  529.                 result = TRUE;
  530.                 break;
  531.             }
  532.             ancestors++;
  533.         }
  534.     }
  535.  
  536.     return result;
  537. }
  538.  
  539. //========================================================================================
  540. // GLOBAL Functions
  541. //========================================================================================
  542.  
  543. //----------------------------------------------------------------------------------------
  544. // ClassDescInheritanceCheck:
  545. //----------------------------------------------------------------------------------------
  546. #pragma segment MAInit
  547.  
  548. #if qDebug
  549.  
  550. void ClassDescInheritanceCheck()
  551. {
  552.     CClassIterator iter;
  553.     MA_ClassReference classDesc;
  554.  
  555.     for (classDesc = iter.FirstClassDesc(); iter.More(); classDesc = iter.NextClassDesc())
  556.     {
  557.         ArrayIndex n = classDesc->CountBaseClasses();
  558.         ArrayIndex i;
  559.         for (i = 1; i <= n; i++)
  560.         {
  561.             MA_ClassReference baseClassDesc = classDesc->GetBaseClass(i);
  562.             if (baseClassDesc->DescendsFrom(classDesc))
  563.             {
  564. #if qDebugMsg
  565.                 fprintf(stderr, "Class %s descends from itself through %s\n", classDesc->GetClassName(), baseClassDesc->GetClassName());
  566. #endif // qDebugMsg
  567.  
  568.                 ProgramBreak("Inheritance loop!");
  569.                 Failure(minErr, 0);
  570.             }
  571.         }
  572.     }
  573. }
  574.  
  575. #endif // qDebug
  576.  
  577. //----------------------------------------------------------------------------------------
  578. // End of UClassDesc.cp
  579.  
  580. #pragma segment Inline
  581.